package com.nulldev.util.web.YouTubeExtractor.extractors;

import java.util.List;
import java.util.Map;

import com.nulldev.util.concurrency.threadIt.v4.emapi.uft.Executable;
import com.nulldev.util.data.Arrays.arrays.FastLists;
import com.nulldev.util.web.YouTubeExtractor.YoutubeExtractionOptions;
import com.nulldev.util.web.YouTubeExtractor.YouTubeExtractor.ABIFeatures;
import com.nulldev.util.web.YouTubeExtractor.video.ExtractedVideo;

public abstract class IYouTubeExtractor implements IYouTubeExtractorConstants {
	public static final double YTE_ABI_VERSION = 2.2;

	/* 2.1 and older */
	/* TODO: Remove me at >=2.2.10 or 2.3 */

	@Deprecated
	public Executable<ExtractedVideo> generateTask(final String videoID, final YoutubeExtractionOptions... options) {
		return generateTask(videoID, null, options);
	}

	@Deprecated
	public Executable<ExtractedVideo> generateTask(final String videoID, final String extraArgs, final YoutubeExtractionOptions... options) {
		return generateTask(IYouTubeExtractorConstants.convertFromLegacy(videoID, extraArgs, options));
	}

	/* 2.2 and newer */

	public abstract Executable<ExtractedVideo> generateTask(final Map<String, Object> arguments);

	public boolean isValidVideoID(final Object videoID) {
		return videoID instanceof String && videoID != null && !((String) videoID).isEmpty() && ((String) videoID).length() > 4;
	}

	public boolean isValidObject(final String type, final Object obj) {
		return type != null && !type.isEmpty() && ARGUMENT_CLASSES.containsKey(type) && obj != null && obj.getClass().isInstance(ARGUMENT_CLASSES.get(type));
	}

	public boolean isValidMap(final Map<String, Object> arguments) {
		return arguments != null && !arguments.isEmpty() && arguments.containsKey(MAP_TYPE_VIDEO_ID) && isValidVideoID(arguments.get(MAP_TYPE_VIDEO_ID));
	}

	public boolean isEnabled(final Map<String, Object> arguments, final String item) {
		// Apparently we want to check Boolean.class not boolean.class...
		return arguments != null && !arguments.isEmpty() && arguments.containsKey(item) && arguments.get(item).getClass() == Boolean.class
				&& ((boolean) arguments.get(item)) == true;
	}

	public Object getFlag(final int flag) {
		return FLAG_NOT_SUPPORTED;
	}

	/* */

	public abstract String getID();

	public abstract int abiVersion();

	public boolean isSupported(final ABIFeatures feature) {
		if (feature == null)
			return false;
		return feature.version >= this.abiVersion();
	}

	public ABIFeatures[] abiProvides() {
		final List<ABIFeatures> feats = FastLists.list(ABIFeatures.values().length);
		final int ABI_VERSION = this.abiVersion();
		for (final ABIFeatures feature : ABIFeatures.values()) {
			if (feature.version <= ABI_VERSION)
				feats.add(feature);
		}
		return feats.toArray(new ABIFeatures[feats.size()]);
	}

	public boolean isLegacyBackend() {
		return false;
	}

	public void enableInstanceDebugging(final boolean value) {
	}

}
